/************************************
*  Copyright (C) 2010 Julien MOTTIN.
*  Contact: julien.mottin@gueydan.eu
*
*  This file is part of Gueydan.
*
*  Gueydan is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  Gueydan is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with Gueydan.  If not, see <http://www.gnu.org/licenses/>.
*
*************************************/
// Local
#include "volume.h"
#include "util.h"

// QtCore
#include <QMap>
#include <QString>

Volume::Volume(const double iVolume, const VolumeUnit iUnit)
{
    _Value = iVolume;
    switch (iUnit)
    {
    case Liter:
        break;
    case Milliliter:
        _Value*=VolCoeffMilliliter;
        break;
    case Teaspoon:
         _Value*=VolCoeffTeaspoon;
         break;
    case Tablespoon:
         _Value*=VolCoeffTablespoon;
        break;
    case Gallon:
        _Value*=VolCoeffGallon;
        break;
    case Cup:
        _Value*=VolCoeffCup;
        break;
    case Pint:
        _Value*=VolCoeffPint;
        break;
    case Quart:
        _Value*=VolCoeffQuart;
        break;
    case LiquidOunce:
        _Value*=VolCoeffOunce;
        break;
    }
}

Volume::Volume(const Volume &iV)
{
    _Value = iV._Value;
}

Volume & Volume::operator=(const Volume &iV)
{
    if (this!=&iV)
    {
        _Value = iV._Value;
    }
    return *this;
}

Volume::~Volume()
{
}

bool Volume::operator==(const Volume &iV) const
{
    return ComparePrecision(_Value,iV._Value,0.0001);
}

bool Volume::operator!=(const Volume &iV) const
{
    return (!ComparePrecision(_Value,iV._Value,0.0001));
}

const Volume Volume::operator+(const Volume &iV) const
{
    return Volume(_Value+iV._Value,Liter);
}

const Volume Volume::operator-(const Volume &iV) const
{
    return Volume(_Value-iV._Value,Liter);
}

bool Volume::operator<(const Volume &iV) const
{
    return (Compare(iV)<0);
}

bool Volume::operator<=(const Volume &iV) const
{
    return (Compare(iV)<=0);
}

bool Volume::operator>(const Volume &iV) const
{
    return (Compare(iV)>0);
}

bool Volume::operator>=(const Volume &iV) const
{
    return (Compare(iV)>=0);
}

double Volume::Value(const VolumeUnit iUnit) const
{
    double oVal = _Value;
    switch (iUnit)
    {
    case Liter:
        break;
    case Milliliter:
        oVal/=VolCoeffMilliliter;
        break;
    case Teaspoon:
         oVal/=VolCoeffTeaspoon;
         break;
    case Tablespoon:
         oVal/=VolCoeffTablespoon;
        break;
    case Gallon:
        oVal/=VolCoeffGallon;
        break;
    case Cup:
        oVal/=VolCoeffCup;
        break;
    case Pint:
        oVal/=VolCoeffPint;
        break;
    case Quart:
        oVal/=VolCoeffQuart;
        break;
    case LiquidOunce:
        oVal/=VolCoeffOunce;
        break;
    }
    return oVal;
}

// Global Volume QMap
static QMap<QString,VolumeUnit> VolumeUnitMap;
static bool VolumeUnitMapInit = false;

void Volume::FromString(const QString &iString, bool *OK)
{
    bool tmpOK = false;

    if (!VolumeUnitMapInit)
    {
        VolumeUnitMap["l"] = Liter;
        VolumeUnitMap["ml"] = Milliliter;
        VolumeUnitMap["cc"] = Milliliter;
        VolumeUnitMap["tsp"] = Teaspoon;
        VolumeUnitMap["tblsp"] = Tablespoon;
        VolumeUnitMap["gal"] = Gallon;
        VolumeUnitMap["cup"] = Cup;
        VolumeUnitMap["qt"] = Quart;
        VolumeUnitMap["pt"] = Pint;
        VolumeUnitMap["oz"] = LiquidOunce;
        VolumeUnitMapInit = true;
    }

    QString Unit;
    double Val;
    StringToUnit(iString,Val,Unit);

    // Case no Unit
    if (Unit.isEmpty())
    {
        // Just copy value
        _Value = Val;
        tmpOK = true;
    }
    else
    {
        if (VolumeUnitMap.contains(Unit))
        {
            // Build volume with proper unit
            VolumeUnit zeUnit = VolumeUnitMap[Unit];
            (*this)=Volume(Val,zeUnit);
            tmpOK = true;
        }
    }

    if (0!=OK)
        (*OK)=tmpOK;
}

double Volume::Compare(const Volume &iV) const
{
    return (_Value - iV._Value);
}
